package cn.hzc.fortess.core.shiro;

import cn.hzc.fortess.core.common.BizErrorEnum;
import cn.hzc.fortess.core.common.exception.ServiceException;
import cn.hzc.fortess.system.entity.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;

import java.util.Random;

public final class ShiroKit {

    private ShiroKit() {
    }

    public static final String NAMES_DELIMETER = ",";

    /**
     * 加盐参数
     */
    public final static String hashAlgorithmName = "MD5";

    /**
     * 循环次数
     */
    public final static int hashIterations = 1024;

    /**
     * shiro密码加密工具类
     *
     * @param credentials 密码
     * @param saltSource  密码盐
     * @return
     */
    public static String md5(String credentials, String saltSource) {
        ByteSource salt = new Md5Hash(saltSource);
        return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations).toString();
    }

    public static String getRandomPwdString() {
        int length=8;
        String base = "abcdefg23456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 获取随机盐值
     *
     * @param length
     * @return
     */
    public static String getRandomSalt(int length) {
        return getRandomString(length);
    }
    public static String getRandomSalt() {
        return getRandomSalt(5);
    }

    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }


    public static ShiroUser getUser() {
        if (isGuest()) {
            return null;
        } else {
            return (ShiroUser) getSubject().getPrincipals().getPrimaryPrincipal();
        }
    }


    public static ShiroUser getUserNotNull() {
        if (isGuest()) {
            throw new ServiceException(BizErrorEnum.NOT_LOGIN.getCode(), BizErrorEnum.NOT_LOGIN.getMessage());
        } else {
            return (ShiroUser) getSubject().getPrincipals().getPrimaryPrincipal();
        }
    }


    public static Session getSession() {
        return getSubject().getSession();
    }


    public static <T> T getSessionAttr(String key) {
        Session session = getSession();
        return session != null ? (T) session.getAttribute(key) : null;
    }


    public static void setSessionAttr(String key, Object value) {
        Session session = getSession();
        session.setAttribute(key, value);
    }


    public static void removeSessionAttr(String key) {
        Session session = getSession();
        if (session != null) {
            session.removeAttribute(key);
        }
    }


    public static boolean hasRole(String roleName) {
        return getSubject() != null && StringUtils.isNotBlank(roleName) && getSubject().hasRole(roleName);
    }


    public static boolean lacksRole(String roleName) {
        return !hasRole(roleName);
    }


    public static boolean hasAnyRoles(Object[] roleNames) {
        Subject subject = getSubject();
        for (Object role : roleNames) {
            if (subject.hasRole(role.toString().trim())) {
                return true;
            }
        }

        return false;
    }


    public static boolean hasAllRoles(Object[] roleNames) {
        Subject subject = getSubject();
        for (Object role : roleNames) {
            if (!subject.hasRole(role.toString().trim())) {
                return false;
            }
        }

        return true;
    }


    public static boolean hasPermission(String permission) {
        return getSubject() != null && StringUtils.isNotBlank(permission) && getSubject().isPermitted(permission);
    }

    public static boolean hasAllPermission(Object[] permissions) {
        for (Object permission : permissions) {
            if (!hasPermission(permission.toString())) {
                return false;
            }
        }
        return true;
    }


    public static boolean hasAnyPermission(Object[] permissions) {
        for (Object permission : permissions) {
            if (hasPermission(permission.toString())) {
                return true;
            }
        }
        return false;
    }

    public static boolean lacksPermission(String permission) {
        return !hasPermission(permission);
    }


    public static boolean isAuthenticated() {
        return getSubject() != null && getSubject().isAuthenticated();
    }


    public static boolean notAuthenticated() {
        return !isAuthenticated();
    }


    public static boolean isUser() {
        return getSubject() != null && getSubject().getPrincipal() != null;
    }


    public static boolean isGuest() {
        return !isUser();
    }


    private static String principal() {
        if (getSubject() != null) {
            Object principal = getSubject().getPrincipal();
            return principal.toString();
        }
        return "";
    }


    public static boolean isAdmin() {
        return getUser().isAdministrator();
    }


    public static ShiroUser createShiroUser(User user) {

        ShiroUser shiroUser = new ShiroUser();

        if (user == null) {
            return shiroUser;
        }

        shiroUser.setId(user.getUserId());
        shiroUser.setAccount(user.getAccount());
        shiroUser.setDeptId(user.getDeptId());
        shiroUser.setName(user.getUserName());
        shiroUser.setEmail(user.getEmail());
        shiroUser.setAvatar(user.getAvatar());
        shiroUser.setDeptName(user.getDeptName());
        shiroUser.setLesseeId(user.getLesseeId());

        return shiroUser;
    }

}
